#include "Scene_PCH.h"
#include "Level.h"

/*--------------------------------------------------------------------------*/

Level::Level() :
	m_width(0),
	m_height(0),
	m_heightmap(NULL),
	m_maxAllowedHeight(50.0f),
	m_minAllowedHeight(-50.0f),
	m_quadSize(100)
{

}

/*--------------------------------------------------------------------------*/

Level::~Level()
{
	if (m_heightmap)
	{
		delete [] m_heightmap;
		m_heightmap = NULL;
	}
}

/*--------------------------------------------------------------------------*/

float Level::GetHeight( int x, int y )
{
	if (x < 0 || x >= m_width)
	{
		return m_minAllowedHeight;
	}
	else if (y < 0 || y >= m_height)
	{
		return m_minAllowedHeight;
	}

	return m_heightmap[x + m_width * y];
}

/*--------------------------------------------------------------------------*/

void Level::Load( const std::string& name )
{
	LoadHeightmap(name);

	bInitData initdata;
	initdata.restitution = 0.95f;
	initdata.position.y = 0.0f;
	initdata.mass = 0.0f;
	
	bInfinitePlane* plane = new bInfinitePlane(g_Scene->GetWorldMgr()->GetWorld(), m_minAllowedHeight - 1.0f, initdata);
	g_Scene->GetWorldMgr()->AddObject(name + std::to_string(rand()), plane);

	__Check(m_width % m_quadSize == 0);
	__Check(m_height % m_quadSize == 0);

	for (int x = 0; x < m_width/m_quadSize; ++x)
	{
		for (int z = 0; z < m_height/m_quadSize; ++z)
		{
			initdata.position.x = x * m_quadSize + m_quadSize / 2;
			initdata.position.z = z * m_quadSize + m_quadSize / 2;

			TerrainInit ti;
			ti.m_size = m_quadSize + 1;

			bTerrain* plane = new bTerrain(g_Scene->GetWorldMgr()->GetWorld(), initdata, ti);
			g_Scene->GetWorldMgr()->AddObject(name + std::to_string(rand()), plane);
		}
	}
}

/*--------------------------------------------------------------------------*/

static unsigned char getpixel(SDL_Surface *s, int x, int y) { 
	uchar* data = (uchar*) s->pixels;
	uint offset = (x * s->format->BytesPerPixel) + (y * s->pitch);

	uchar* a = (uchar*) data[offset];

	return data[offset];//((unsigned int*)s->pixels)[y*(s->pitch/sizeof(unsigned int)) + x/3]; 
} 

void Level::LoadHeightmap( const std::string& levelname )
{
	SDL_Surface* hmap = SDL_LoadBMP(("../../build/data/levels/" + levelname + "/heightmap.bmp").c_str());
	
	if (hmap == NULL)
	{
		__Error("Unable to load heightmap for level %s: %s", levelname.c_str(), SDL_GetError());
		return;
	}

	m_width		= hmap->w;
	m_height	= hmap->h;

	m_heightmap = new float[m_width * m_height];

	for (int x = 0; x < m_width; ++x)
	{
		for (int y = 0; y < m_height; ++y)
		{
			m_heightmap[x + m_width * y] = getpixel(hmap, x, y) / 255.0f;// * 4.0f - 500.0f;
			m_heightmap[x + m_width * y] *= std::abs(m_maxAllowedHeight - m_minAllowedHeight);
			m_heightmap[x + m_width * y] += m_minAllowedHeight;
		}
	}

	for (int x = 2; x < m_width - 2; ++x)
	{
		for (int y = 2; y < m_height - 2; ++y)
		{
			float h = 0.0f;

			for (int xx = -2; xx <= 2; ++xx)
			{
				for (int yy = -2; yy <= 2; ++yy)
				{
					h += m_heightmap[x + xx + m_width * (y + yy)];
				}
			}

			m_heightmap[x + m_width * y] = glm::clamp(h / 25.0f, m_minAllowedHeight, m_maxAllowedHeight);
		}
	}

	SDL_FreeSurface(hmap);
}

/*--------------------------------------------------------------------------*/

float Level::GetMaxHeight() const
{
	return m_maxAllowedHeight;
}

/*--------------------------------------------------------------------------*/

float Level::GetMinHeight() const
{
	return m_minAllowedHeight;
}

/*--------------------------------------------------------------------------*/
